package com.chansos.dubbogo.project_generator;

import com.chansos.dubbogo.ui.ComponentsGroup;
import com.chansos.dubbogo.util.TemplateUtils;
import com.intellij.openapi.project.Project;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EmptyProjectGenerator implements ProjectGenerator {
    private final String basePath = "/project_template/empty_project";

    private final List<TemplateFileModel> templateFiles = new ArrayList<>() {{

        // Go Module
        add(new TemplateFileModel(basePath, "/mod", "/go.mod"));

        // Application main
        add(new TemplateFileModel(basePath, "/cmd/main.go1", "/cmd/main.go"));

        // Application config file
        add(new TemplateFileModel(basePath, "/resources/application.yml", "/resources/application.yml"));

        // Dubbo Go Sample
        add(new TemplateFileModel(basePath, "/service/api_ping.go1", "/service/api_ping.go"));
        add(new TemplateFileModel(basePath, "/dto/api_ping.go1", "/dto/api_ping.go"));
        add(new TemplateFileModel(basePath, "/service/dubbo_api_ping.go1", "/service/dubbo_api_ping.go"));

        // Project Run Configuration
        add(new TemplateFileModel(basePath, "/.run/main.run.xml", "/.run/main.run.xml"));

        // Other files
        add(new TemplateFileModel(basePath, "/README.md", "/README.md"));
        add(new TemplateFileModel(basePath, "/README_CN.md", "/README_CN.md"));
        add(new TemplateFileModel(basePath, "/.gitignore", "/.gitignore"));
    }};

    // Web Service
    private final List<TemplateFileModel> webServiceTemplateFiles = new ArrayList<>() {{
        add(new TemplateFileModel(basePath, "/controller/controller_entry.go1", "/controller/controller_entry.go"));
        add(new TemplateFileModel(basePath, "/controller/api_home.go1", "/controller/api_home.go"));
    }};

    // Memory Cache
    private final List<TemplateFileModel> memoryCacheTemplateFiles = new ArrayList<>() {{
    }};

    // Database
    private final List<TemplateFileModel> databaseTemplateFiles = new ArrayList<>() {{
    }};


    private ComponentsGroup.ComponentConfigs components;

    private final Map<String, String> componentDefaultArgs = new HashMap<>() {{
        put("${component-mod-import}", ComponentsGroup.componentModVersion);

        put("${web-service-yml-config}", "");
        put("${web-service-mod-import}", "");
        put("${web-service-main-import}", "");
        put("${web-service-main-setup-hook-func}", "");
        put("${web-service-main-setup-hook-statement}", "");

        put("${memory-cache-yml-config}", "");
        put("${memory-cache-mod-import}", "");
        put("${memory-cache-main-import}", "");
        put("${memory-cache-main-setup-hook-func}", "");
        put("${memory-cache-main-setup-hook-statement}", "");

        put("${database-yml-config}", "");
        put("${database-mod-import}", "");
        put("${database-main-import}", "");
        put("${database-main-setup-hook-func}", "");
        put("${database-main-setup-hook-statement}", "");
    }};

    @Override
    public void generate(Project projectName, String path, Map<String, String> args) {
        args.putAll(componentDefaultArgs);
        List<TemplateFileModel> allTemplateFile = new ArrayList<>(templateFiles);
        ComponentsGroup.WebServiceConfig webServiceConfig = components.getWebServiceConfig();
        if (webServiceConfig != null) {
            allTemplateFile.addAll(webServiceTemplateFiles);
            args.put("${web-service-yml-config}", TemplateUtils.replaceContent(webServiceConfig.toString(), args));
            args.put("${web-service-mod-import}", webServiceConfig.modImport());
            args.put("${web-service-main-import}", webServiceConfig.mainImport());
            args.put("${web-service-main-setup-hook-func}", webServiceConfig.mainSetupHookFunc());
            args.put("${web-service-main-setup-hook-statement}", webServiceConfig.mainSetupHookStatement());
        }
        ComponentsGroup.MemoryCacheConfig memoryCacheConfig = components.getMemoryCacheConfig();
        if (memoryCacheConfig != null) {
            allTemplateFile.addAll(memoryCacheTemplateFiles);
            args.put("${memory-cache-yml-config}", TemplateUtils.replaceContent(memoryCacheConfig.toString(), args));
            args.put("${memory-cache-mod-import}", memoryCacheConfig.modImport());
            args.put("${memory-cache-main-import}", memoryCacheConfig.mainImport());
            args.put("${memory-cache-main-setup-hook-func}", memoryCacheConfig.mainSetupHookFunc());
            args.put("${memory-cache-main-setup-hook-statement}", memoryCacheConfig.mainSetupHookStatement());
        }
        ComponentsGroup.DatabaseConfig databaseConfig = components.getDatabaseConfig();
        if (databaseConfig != null) {
            allTemplateFile.addAll(databaseTemplateFiles);
            args.put("${database-yml-config}", TemplateUtils.replaceContent(databaseConfig.toString(), args));
            args.put("${database-mod-import}", databaseConfig.modImport());
            args.put("${database-main-import}", databaseConfig.mainImport());
            args.put("${database-main-setup-hook-func}", databaseConfig.mainSetupHookFunc());
            args.put("${database-main-setup-hook-statement}", databaseConfig.mainSetupHookStatement());
        }

        for (TemplateFileModel templateFile : allTemplateFile) {
            String content = TemplateUtils.readTemplate(templateFile.getTemplatePath());
            if (content != null) {
                content = TemplateUtils.replaceContent(content, args);
                templateFile.setModulePath(path);
                TemplateUtils.writeTemplate(templateFile.getTargetPath(), content);
            }
        }
//        try {
//            GeneralCommandLine go_mod_tidy = new GeneralCommandLine("go");
//            go_mod_tidy.withEnvironment("GO111MODULE", "on");
//            go_mod_tidy.withParameters("get", "-u", "dubbo.apache.org/dubbo-go/v3");
//            go_mod_tidy.setWorkDirectory(path);
//            Process process = go_mod_tidy.createProcess();
//            process.waitFor();
//            System.out.println(process.exitValue());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }


    public void setComponents(ComponentsGroup.ComponentConfigs components) {
        this.components = components;
    }
}
